// Problem 043: Sub-string divisibility
// The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property.
// Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we note the following:
// d2d3d4=406 is divisible by 2
// d3d4d5=063 is divisible by 3
// d4d5d6=635 is divisible by 5
// d5d6d7=357 is divisible by 7
// d6d7d8=572 is divisible by 11
// d7d8d9=728 is divisible by 13
// d8d9d10=289 is divisible by 17
// Find the sum of all 0 to 9 pandigital numbers with this property.

package main

import (
	"bytes"
	"fmt"
	"projecteuler/euler"
	"strconv"
)

func p043() {
	// the middle digit of m07 must be 5/2, since the last shift meet a 5's multiple.
	m07 := [...]string{"056", "105", "154", "203", "259", "301", "308", "350", "357", "406", "504", "602", "609", "651", "658", "756", "805", "854", "903", "952"}
	m11 := [...]string{"132", "143", "154", "165", "176", "187", "198", "209", "231", "253", "264", "275", "286", "297", "308", "319", "341", "352", "374", "385", "396", "407", "418", "429", "451", "462", "473", "495", "506", "517", "528", "539", "561", "572", "583", "594", "605", "627", "638", "649", "671", "682", "693", "704", "715", "726", "748", "759", "781", "792", "803", "814", "825", "836", "847", "869", "891", "902", "913", "924", "935", "946", "957", "968"}
	m13 := [...]string{"013", "026", "039", "052", "065", "078", "091", "104", "130", "143", "156", "169", "182", "195", "208", "234", "247", "260", "273", "286", "312", "325", "351", "364", "390", "403", "416", "429", "468", "481", "494", "507", "520", "546", "572", "598", "624", "637", "650", "689", "702", "715", "728", "741", "754", "780", "793", "806", "819", "832", "845", "871", "897", "910", "923", "936", "962", "975"}
	m17 := [...]string{"017", "034", "051", "068", "085", "102", "136", "153", "170", "187", "204", "238", "272", "289", "306", "340", "357", "374", "391", "408", "425", "459", "476", "493", "510", "527", "561", "578", "612", "629", "680", "697", "714", "731", "748", "765", "782", "816", "850", "867", "901", "918", "935", "952", "986"}
	ans := 0

	for _, n17 := range m17 {
		for _, n13 := range m13 {
			if n13[1:3] == n17[0:2] {
				if str1 := n13[0:1] + n17; euler.IsUniqueDigits(str1) {
					for _, n11 := range m11 {
						if n11[1:3] == str1[0:2] {
							if str2 := n11[0:1] + str1; euler.IsUniqueDigits(str2) {
								for _, n07 := range m07 {
									if n07[1:3] == str2[0:2] {
										if str3 := n07[0:1] + str2; (str3[1:2] == "5" || str3[1:2] == "0") && euler.IsUniqueDigits(str3) {
											// only two: 357289,952867
											digits := []byte("0123456789")
											for _, c := range []byte(str3) {
												idx := bytes.IndexByte(digits, c)
												digits = append(digits[0:idx], digits[idx+1:]...)
											}
											ans += handle043(string(digits), str3)
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	fmt.Println("Problem 043:", ans)
}

func handle043(s, l string) int {
	ans := 0
	per := euler.Permutations(len(s), s)
	for _, v := range per {
		if v[0:1] == "0" {
			continue
		}
		if i, ok := strconv.Atoi(v[3:4]); ok == nil {
			if i%2 != 0 {
				continue
			}
		}
		if i, ok := strconv.Atoi(v[2:4]); ok == nil {
			if x, ok := strconv.Atoi(l[0:1]); ok == nil {
				if (i*10+x)%3 != 0 {
					continue
				}
			}
		}
		if x, ok := strconv.Atoi(v + l); ok == nil {
			ans += x
		}
	}
	return ans
}
